package service

import (
	"context"
	"database/sql"

	dbmodel "gitee.com/hp-huiw/family-expense-api/internal/db/model"
	"gitee.com/hp-huiw/family-expense-api/internal/repository"
	"gitee.com/hp-huiw/my-go-core/date"
	"gitee.com/hp-huiw/my-go-core/security"
	"gitee.com/hp-huiw/my-go-core/util"
)

// The public member is shared within entire application.
// var CachedRequestMap []model.RequestMap

type RequestMapService interface {
	Initialize(ctx context.Context) error
}

// Returns the instance of private member, authService, which implements the RequestMapService interface.
func NewRequestMapService(db *sql.DB) RequestMapService {
	return &requestMapService{
		db:                   db,
		requestMapRepository: repository.NewRequestMapRepository(db),
	}
}

// Initializes all default request maps if needed.
func (s *requestMapService) Initialize(ctx context.Context) error {
	exists, err := s.requestMapRepository.Exists(ctx)

	if err != nil {
		return err
	}

	if !exists {
		models := []dbmodel.RequestMap{
			{
				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapPermitAll,
				URL:             "/app-error-report/**",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{
				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapPermitAll,
				URL:             "/authentication/**",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},

			{

				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapIsAuthenticated,
				URL:             "/map-location/**",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{

				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapIsAuthenticated,
				HTTPMethod:      util.AnyPtr(util.HttpPost),
				URL:             "/authentication/unregister",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{

				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapIsAuthenticated,
				HTTPMethod:      util.AnyPtr(util.HttpGet),
				URL:             "/app-release-log/**",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{

				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapIsAuthenticated,
				URL:             "/account-group/**",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{

				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapIsAuthenticated,
				HTTPMethod:      util.AnyPtr(util.HttpGet),
				URL:             "/account-group-user/**",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{

				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapIsAuthenticated,
				HTTPMethod:      util.AnyPtr(util.HttpPost),
				URL:             "/account-group/quit",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{

				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapIsAuthenticated,
				HTTPMethod:      util.AnyPtr(util.HttpGet),
				URL:             "/bank/**",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{

				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapIsAuthenticated,
				HTTPMethod:      util.AnyPtr(util.HttpGet),
				URL:             "/bank-card/**",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{

				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapIsAuthenticated,
				HTTPMethod:      util.AnyPtr(util.HttpGet),
				URL:             "/data-initialization/**",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{

				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapIsAuthenticated,
				URL:             "/file/**",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{

				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapIsAuthenticated,
				HTTPMethod:      util.AnyPtr(util.HttpGet),
				URL:             "/income-expense-analysis/**",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{

				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapIsAuthenticated,
				HTTPMethod:      util.AnyPtr(util.HttpGet),
				URL:             "/income-expense-detail/**",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{

				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapIsAuthenticated,
				HTTPMethod:      util.AnyPtr(util.HttpGet),
				URL:             "/income-expense-detail-type/query-by-account-group",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{

				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapIsAuthenticated,
				HTTPMethod:      util.AnyPtr(util.HttpGet),
				URL:             "/income-expense-detail-type/query-analysis-not-included-detail-types",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{

				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapIsAuthenticated,
				URL:             "/join-account-group-request/**",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{

				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapIsAuthenticated,
				HTTPMethod:      util.AnyPtr(util.HttpGet),
				URL:             "/journey/**",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{

				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapIsAuthenticated,
				HTTPMethod:      util.AnyPtr(util.HttpGet),
				URL:             "/journey-income-expense-detail/**",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{

				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapIsAuthenticated,
				HTTPMethod:      util.AnyPtr(util.HttpGet),
				URL:             "/region/**",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{

				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapIsAuthenticated,
				URL:             "/user/**",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{

				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapIsAuthenticated,
				URL:             "/user-active-token/**",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			// This is used by upload package.
			// We need to check and refresh the token if it can.
			// Remember to set this url as isFullyAuthenticated() in spring security rest.
			// We are making a http get request to this url before upload.
			// It's the easy way to do the auto-refresh for upload.
			{

				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapIsAuthenticated,
				HTTPMethod:      util.AnyPtr(util.HttpGet),
				URL:             "/token-check/**",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{
				ID: util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapHasAnyRole([]string{
					security.RoleAccountGroupUser,
					security.RoleAccountGroupAdmin,
				}),
				HTTPMethod:  util.AnyPtr(util.HttpPost),
				URL:         "/income-expense-detail/**",
				DateCreated: date.GetCurrentDate(),
				LastUpdated: date.GetCurrentDate(),
			},
			{
				ID: util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapHasAnyRole([]string{
					security.RoleAccountGroupUser,
					security.RoleAccountGroupAdmin,
				}),
				HTTPMethod:  util.AnyPtr(util.HttpPost),
				URL:         "/journey/**",
				DateCreated: date.GetCurrentDate(),
				LastUpdated: date.GetCurrentDate(),
			},
			{
				ID: util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapHasAnyRole([]string{
					security.RoleAccountGroupUser,
					security.RoleAccountGroupAdmin,
				}),
				HTTPMethod:  util.AnyPtr(util.HttpPost),
				URL:         "/journey-income-expense-detail/**",
				DateCreated: date.GetCurrentDate(),
				LastUpdated: date.GetCurrentDate(),
			},
			{
				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapHasRole(security.RoleAccountGroupAdmin),
				HTTPMethod:      util.AnyPtr(util.HttpPost),
				URL:             "/account-group/**",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{
				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapHasRole(security.RoleAccountGroupAdmin),
				HTTPMethod:      util.AnyPtr(util.HttpPost),
				URL:             "/account-group-user/**",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{
				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapHasRole(security.RoleAccountGroupAdmin),
				HTTPMethod:      util.AnyPtr(util.HttpPost),
				URL:             "/bank-card/**",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{
				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapHasRole(security.RoleAccountGroupAdmin),
				HTTPMethod:      util.AnyPtr(util.HttpPost),
				URL:             "/file/upload-avatar",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{
				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapHasRole(security.RoleAccountGroupAdmin),
				HTTPMethod:      util.AnyPtr(util.HttpGet),
				URL:             "/income-expense-detail-type/check-existing",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{
				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapHasRole(security.RoleAccountGroupAdmin),
				HTTPMethod:      util.AnyPtr(util.HttpPost),
				URL:             "/income-expense-detail-type/**",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{
				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapHasRole(security.RoleAccountGroupAdmin),
				HTTPMethod:      util.AnyPtr(util.HttpPost),
				URL:             "/join-account-group-request/send",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{
				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapHasRole(security.RoleAccountGroupAdmin),
				HTTPMethod:      util.AnyPtr(util.HttpGet),
				URL:             "/role/query-non-system-level-roles",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{
				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapHasRole(security.RoleAccountGroupAdmin),
				HTTPMethod:      util.AnyPtr(util.HttpGet),
				URL:             "/user/query-users-not-in-account-group",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{
				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapHasRole(security.RoleAccountGroupAdmin),
				HTTPMethod:      util.AnyPtr(util.HttpPost),
				URL:             "/user/add",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{
				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapHasRole(security.RoleAccountGroupAdmin),
				HTTPMethod:      util.AnyPtr(util.HttpPost),
				URL:             "/user/update-password",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{
				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapHasRole(security.RoleAccountGroupAdmin),
				HTTPMethod:      util.AnyPtr(util.HttpPost),
				URL:             "/user/update-enabled",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
			{
				ID:              util.GenerateUUIDWithoutDashes(),
				ConfigAttribute: security.RequestMapHasRole(security.RoleAccountGroupAdmin),
				HTTPMethod:      util.AnyPtr(util.HttpPost),
				URL:             "/user/delete",
				DateCreated:     date.GetCurrentDate(),
				LastUpdated:     date.GetCurrentDate(),
			},
		}

		err = s.requestMapRepository.BatchInsert(ctx, models)
	}

	return err
}

// Container of RequestMapService functions.
type requestMapService struct {
	db                   *sql.DB
	requestMapRepository repository.RequestMapRepository
}
